#pragma once

#include "WritePixelBuffer.h"
#include "BufferHint.h"
#include "PixelBufferGL3x.h"
#include "TypeConverterGL3x.h"

namespace Renderer
{
	namespace GL3x
	{
		class WritePixelBufferGL3x : public WritePixelBuffer
		{
		public:
			WritePixelBufferGL3x(PixelBufferHint usageHint, int sizeInBytes)
			{
				_bufferObject = new PixelBufferGL3x(GL_PIXEL_UNPACK_BUFFER, TypeConverterGL3x::to_gl_type(usageHint, PixelBufferHintType::Draw), sizeInBytes);
				_usageHint = usageHint;
			}

			~WritePixelBufferGL3x()
			{
				Destroy();
			}

			void Bind()
			{
				_bufferObject->Bind();
			}

			static void UnBind()
			{
				glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
			}


			template<typename T>
			void CopyFromSystemMemory(
				T* bufferInSystemMemory,
				int destinationOffsetInBytes,
				int lengthInBytes)
			{
				_bufferObject->CopyFromSystemMemory(bufferInSystemMemory, destinationOffsetInBytes, lengthInBytes);
			}

			template<typename T>
			T* CopyToSystemMemory(int offsetInBytes, int lengthInBytes)
			{
				return _bufferObject->CopyToSystemMemory(offsetInBytes, lengthInBytes);
			}



			int GetSizeInBytes() const override
			{
				return _bufferObject->GetSizeInBytes();
			}

			PixelBufferHint GetUsageHint() const override
			{
				return _usageHint;
			}

			void Destroy()
			{
				if (_bufferObject)
				{
					_bufferObject->Destroy();
					_bufferObject = 0;
				}
			}

			static BufferHint ToBufferHint(PixelBufferHint usageHint)
			{
				if (usageHint == PixelBufferHint::Stream)
				{
					return BufferHint::StreamDraw;
				}
				else if (usageHint == PixelBufferHint::Static)
				{
					return BufferHint::StaticDraw;
				}
				else
				{
					return BufferHint::DynamicDraw;
				}
			}

		private:
			PixelBufferGL3x* _bufferObject;
			PixelBufferHint _usageHint;
		};
	}
}